package xw4g08;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.List;

import org.openrdf.model.BNode;
import org.openrdf.model.Namespace;
import org.openrdf.model.Statement;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;
import org.openrdf.repository.RepositoryResult;
import org.openrdf.repository.http.HTTPRepository;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFWriter;
import org.openrdf.rio.Rio;

public class StatisticsSPARQL1_1 {

	public static void run() {

		HTTPRepository rep = null;
		RepositoryConnection con = null;
		String preQStr = "SELECT ?p (COUNT(?p) AS ?preNm) WHERE {?s ?p ?o.} GROUP BY ?p";
		String totalQStr = "SELECT (COUNT(?p) AS ?total) WHERE {?s ?p ?o.}";
		Configuration.init();
		List<String> urls = Configuration.REP_URLs;
		try {
			FileOutputStream out = new FileOutputStream(Configuration.STA_OUT);
			
			RDFWriter writer = Rio.createWriter(RDFFormat.N3, out);
			try {
				writer.startRDF();
				
				for(int i = 0;i < Configuration.REP_NUM;i++){
					System.out.println("Colecting statistics from "+urls.get(i));
					rep = new HTTPRepository(urls.get(i));
					try{
						rep.initialize();
						try{
							con = rep.getConnection();
							ValueFactory vf = con.getValueFactory();
							TupleQuery qry = con.prepareTupleQuery(QueryLanguage.SPARQL, preQStr);
							System.out.println("Writing namespaces...");
							handelNS(con,writer);
							writer.handleNamespace("sd", "http://darq.sf.net/dose/0.1#");
							System.out.println("Counting predicates...");
							TupleQueryResult totalNm = qry.evaluate();
							//create the configuration file
							String sd = "http://darq.sf.net/dose/0.1#";
							URI sd_capability = vf.createURI(sd, "capability");
							URI sd_triples = vf.createURI(sd, "triples");
							URI sd_pre = vf.createURI(sd, "predicate");
							URI sd_totalTriples = vf.createURI(sd, "totalTriples");
							URI sd_url = vf.createURI(sd, "url");
							BNode servNode = vf.createBNode("ser"+i);
							
							Statement sta = vf.createStatement(servNode, RDF.TYPE, vf.createURI(sd,"Service"));//[] a sd:Service;
							writer.handleStatement(sta);
							int j = 0;
							System.out.println("Writing predicates to the file");
							while(totalNm.hasNext()){
								BindingSet bind = totalNm.next();
								Value p = bind.getBinding("p").getValue();
								String triNm = bind.getBinding("preNm").getValue().stringValue();
								
								BNode capNode = vf.createBNode("cap"+i+"-"+(j++));
								sta = vf.createStatement(servNode, sd_capability, capNode);
								writer.handleStatement(sta);
								sta = vf.createStatement(capNode, sd_pre, p);
								writer.handleStatement(sta);
								sta = vf.createStatement(capNode, sd_triples, vf.createLiteral(triNm));
								writer.handleStatement(sta);
							}
							totalNm.close();
							
							qry = con.prepareTupleQuery(QueryLanguage.SPARQL, totalQStr);
							System.out.println("Counting total number of triples");
							totalNm = qry.evaluate();
							String total = totalNm.next().getBinding("total").getValue().stringValue();
							writer.handleStatement(vf.createStatement(servNode, sd_totalTriples, vf.createLiteral(total)));
							writer.handleStatement(vf.createStatement(servNode, sd_url, vf.createURI(urls.get(i))));
							writer.handleComment("#############################");
							totalNm.close();
							
						} catch (MalformedQueryException e) {
							e.printStackTrace();
						} catch (QueryEvaluationException e) {
							e.printStackTrace();
						}
						finally{
							if(con.isOpen())
								con.close();
						}
					}catch (RepositoryException e){
						e.printStackTrace();
					}
					finally{
							try {
								rep.shutDown();
							} catch (RepositoryException e) {
								e.printStackTrace();
							}
					}
			}
			writer.endRDF();
			} catch (RDFHandlerException e1) {
				e1.printStackTrace();
			}
		} catch (FileNotFoundException e2) {
			e2.printStackTrace();
		}
		

		
		
	}
	
	public static void handelNS(RepositoryConnection con, RDFWriter writer) throws RepositoryException, RDFHandlerException {

		RepositoryResult<Namespace> nmSpaces = con.getNamespaces();
		
		while(nmSpaces.hasNext()){
			Namespace ns = nmSpaces.next();
			writer.handleNamespace(ns.getPrefix(),ns.getName());
		}
		nmSpaces.close();
	}

}
